

from rest_framework import serializers
from goods.models import SKU,SKUSpecification,GoodsCategory,SPU
from goods.models import GoodsSpecification,SpecificationOption
from django.db import transaction

class SpecOptModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = [
            'id',
            'value'
        ]


class SPUSpecModelSerializer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField()
    spu_id = serializers.IntegerField()

    # 当前规格关联的"多个"选项表数据
    options = SpecOptModelSerializer(many=True)

    class Meta:
        model = GoodsSpecification
        fields = [
            'id',
            'name',
            'spu',
            'spu_id',
            'options'
        ]




class SPUSimpleModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        fields = ['id', 'name']



class GoodsCategorySimpleSeializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = [
            'id',
            'name'
        ]



class SKUSpecModelSerializer(serializers.ModelSerializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        model = SKUSpecification
        fields = [
            'spec_id',
            'option_id'
        ]

from celery_tasks.html.tasks import generate_static_sku_detail_html
class SKUModelSerializer(serializers.ModelSerializer):

    # spu、category是外间关联字段，默认映射过来的类型是PrimaryKeyRelatedField,序列化结果是主键
    # spu_id,category_id是外间关联对象的隐藏字段，需要自己手动定义处理
    spu = serializers.StringRelatedField()
    spu_id = serializers.IntegerField()
    category = serializers.StringRelatedField()
    category_id = serializers.IntegerField()

    # 代表"多个"从表SKUSpecification模型类对象
    specs = SKUSpecModelSerializer(many=True)

    class Meta:
        model = SKU
        fields = "__all__"


    def update(self, instance, validated_data):
        # 设置默认图片(可做可不做！)
        validated_data.setdefault('default_image_url', 'group1/M00/00/02/CtM3BVrRdMSAaDUtAAVslh9vkK04466364')
        # 用户选择的规格和选项信息从有效数据中剔除
        specs = validated_data.pop('specs')
        sku = None
        with transaction.atomic():
            save_id = transaction.savepoint()

            try:
                # 1、更新主表数据
                sku = super().update(instance, validated_data)
                # 2、更新从表数据：先删除原有规格和选项，在插入新的规格和选项
                # 删除原有
                SKUSpecification.objects.filter(sku_id=sku.id).delete()
                # 插入新的
                # sku_id  spec_id  option_id
                for spec in specs:
                    # spec = {"spec_id": "6", "option_id": 13}
                    spec['sku_id'] = sku.id  # {"spec_id": "6", "option_id": 13, "sku_id: 16}
                    SKUSpecification.objects.create(**spec)
            except Exception as e:
                transaction.savepoint_rollback(save_id)

            transaction.savepoint_commit(save_id)

        # 事务执行成功，说明新增了一个sku商品,生成静态话页面
        generate_static_sku_detail_html.delay(sku.id)

        return instance


    def create(self, validated_data):
        # 重写的原因：模型类序列化器此时无法帮助我们构建中间表数据记录当前sku的规格和选项信息

        # 设置默认图片(可做可不做！)
        validated_data.setdefault('default_image_url', 'group1/M00/00/02/CtM3BVrRdMSAaDUtAAVslh9vkK04466364')

        # 用户选择的规格和选项信息从有效数据中剔除
        specs = validated_data.pop('specs')
        sku = None
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                # 1、新增主表数据：新建sku对象
                sku = super().create(validated_data)
                # 2、插入中间表数据记录规格和选信息
                # sku_id  spec_id  option_id
                for spec in specs:
                    # spec = {"spec_id": "6", "option_id": 13}
                    spec['sku_id'] = sku.id # {"spec_id": "6", "option_id": 13, "sku_id: 16}
                    SKUSpecification.objects.create(**spec)

            except Exception as e:
                transaction.savepoint_rollback(save_id)

            transaction.savepoint_commit(save_id)

        # 事务执行成功，说明新增了一个sku商品,生成静态话页面
        generate_static_sku_detail_html.delay(sku.id)

        return sku
















